home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.3 Development Libraries / SGI IRIX 6.3 Development Libraries.iso / dist6.3 / gl_dev.idb / usr / share / src / OpenGL / toolkits / libisfast / isfast.c.z / isfast.c
Encoding:
C/C++ Source or Header  |  1996-12-06  |  19.7 KB  |  755 lines

  1. /*****************************************************************************
  2.  * isfast - routines for subjectively assessing performance of selected
  3.  *        OpenGL drawing operations
  4.  *
  5.  * Overview:
  6.  *
  7.  *    The main entry points (ImmediateModeIsFast, etc.) each run two
  8.  *    tests:  a baseline test, and a second test that uses the
  9.  *    attributes or rendering mode of interest.  They compare the
  10.  *    performance of the two tests, and (usually) conclude the mode
  11.  *    of interest ``is fast'' if it's at least half as fast as the
  12.  *    baseline test.
  13.  *
  14.  *    To run a test, the main entry points call RunTest().  RunTest()
  15.  *    uses the performance database library (libpdb) to check the
  16.  *    database for the desired test result.  If the result is already
  17.  *    in the database, then that previous result is just returned.
  18.  *    Otherwise, RunTest() calls Measure() to measure the performance
  19.  *    of the desired operation, and then records the result in the
  20.  *    database for future use.
  21.  *
  22.  *    Measure() opens a window for OpenGL drawing and initializes the
  23.  *    OpenGL rendering context with some useful defaults.  It then
  24.  *    invokes the test routine supplied by RunTest(), which saves the
  25.  *    measured performance in a global variable.  Finally, it closes
  26.  *    the window and returns to RunTest().
  27.  *
  28.  *    The individual test routines (BaseTriangleTest, for example)
  29.  *    that are invoked by Measure() just set any additional OpenGL
  30.  *    state that they need, clear the drawing buffers, and call the
  31.  *    libpdb routine pdbMeasureRate() to measure the performance of
  32.  *    a drawing routine.  Most of the time, they store the primitives
  33.  *    in a display list, and the drawing routine just calls that
  34.  *    display list.  (This yields more meaningful results than
  35.  *    immediate-mode drawing when the test machine is being accessed
  36.  *    across a network.)  So the usual division of labor is that the
  37.  *    test routine performs one-time setup of state information, and
  38.  *    the drawing routine performs all the repeated rendering.
  39.  *
  40.  *    One subtlety:  libpdb needs to calibrate its measuring routines.
  41.  *    This calibration can take a significant percentage of the time
  42.  *    required to run isfast, so each of the test routines takes care
  43.  *    to ensure that calibration is performed only once.
  44.  *
  45.  * History:
  46.  *
  47.  *    1.0    9/93    akin    Written.  See accompanying README for
  48.  *                rationale and examples.
  49.  *    2.0    5/95    akin    Heavily modified.  Eliminated dependence
  50.  *                on toolkits, made calibration operation
  51.  *                less frequent (thus speeding up testing),
  52.  *                used new pdb which includes support for
  53.  *                versioning, and restructured tests to make
  54.  *                better use of display lists (so that running
  55.  *                remotely yields more useful results).
  56.  *    2.1    7/8/95    akin    Added line antialiasing.
  57.  *****************************************************************************/
  58.  
  59.  
  60. #include <stdio.h>
  61. #include <GL/glx.h>
  62. #include <GL/glu.h>
  63. #include "pdb.h"
  64. #include "isfast.h"
  65.  
  66.  
  67. static double    AALineRate = 0.0;
  68. static double    BaseLineRate = 0.0;
  69. static double    BaseTriangleRate = 0.0;
  70. static double    ImmediateModeRate = 0.0;
  71. static double    NoDepthBufferRate = 0.0;
  72. static double    StencillingRate = 0.0;
  73. static double    TextureMappingRate = 0.0;
  74. static int    Calibrate = 1;
  75. static char*    Version = NULL;
  76. static char*    ServerName = NULL;
  77.  
  78. static const char* cIsFast = "IsFast";
  79. static const char* cBaseLine = "BaseLine";
  80. static const char* cBaseTriangle = "BaseTriangle";
  81.  
  82.  
  83. static void    AALineTest        (void);
  84. static void    BaseLineTest        (void);
  85. static void    BaseTriangleTest    (void);
  86. static void    DrawBaseLines        (void);
  87. static void    DrawBaseTriangles    (void);
  88. static void    DrawDisplayList        (void);
  89. static void    ImmediateModeTest    (void);
  90. static int    Measure            (const char*    windowType,
  91.                      const char*    windowTitle,
  92.                      void        (*testFunc)(void));
  93. static void    NoDepthBufferTest    (void);
  94. static int    RunTest            (void        (*testFunction)(void),
  95.                      const char*    testName,
  96.                      double*    rate,
  97.                      char*        windowType);
  98. static void    StencillingTest        (void);
  99. static void    TextureMappingTest    (void);
  100.  
  101.  
  102. static const GLfloat Vertex[] = {
  103.      0.9,  0.0,
  104.      0.85, 0.1,
  105.      0.8,  0.0,
  106.      0.75, 0.1,
  107.      0.7,  0.0,
  108.      0.65, 0.1,
  109.      0.6,  0.0,
  110.      0.55, 0.1,
  111.      0.5,  0.0,
  112.      0.45, 0.1,
  113.      0.4,  0.0,
  114.      0.35, 0.1,
  115.      0.3,  0.0,
  116.      0.25, 0.1,
  117.      0.2,  0.0,
  118.      0.15, 0.1,
  119.      0.1,  0.0,
  120.      0.05, 0.1,
  121.      0.0,  0.0,
  122.     -0.05, 0.1,
  123.     -0.1,  0.0,
  124.     -0.15, 0.1,
  125.     -0.2,  0.0,
  126.     -0.25, 0.1,
  127.     -0.3,  0.0,
  128.     -0.35, 0.1,
  129.     -0.4,  0.0,
  130.     -0.45, 0.1,
  131.     -0.5,  0.0,
  132.     -0.55, 0.1,
  133.     -0.6,  0.0,
  134.     -0.65, 0.1,
  135.     -0.7,  0.0,
  136.     -0.75, 0.1,
  137.     -0.8,  0.0,
  138.     -0.85, 0.1,
  139.     -0.9,  0.0
  140.     };
  141.  
  142.  
  143. /*****************************************************************************
  144.  * AALineTest - measure drawing rate for antialiased lines
  145.  *****************************************************************************/
  146.  
  147. static void
  148. AALineTest() {
  149.     glClear(GL_COLOR_BUFFER_BIT);
  150.     glDisable(GL_LIGHTING);
  151.     glDisable(GL_COLOR_MATERIAL);
  152.     glShadeModel(GL_FLAT);
  153.  
  154.     glEnable(GL_LINE_SMOOTH);
  155.     glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
  156.     glEnable(GL_BLEND);
  157.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  158.  
  159.     glNewList(1, GL_COMPILE);
  160.         DrawBaseLines();
  161.     glEndList();
  162.  
  163.     pdbMeasureRate(glFinish, DrawDisplayList, glFinish, Calibrate,
  164.         &AALineRate);
  165.     Calibrate = 0;
  166.  
  167.     glDeleteLists(1, 1);
  168.     }
  169.  
  170.  
  171. /*****************************************************************************
  172.  * BaseLineTest - measure drawing rate for baseline lines
  173.  *****************************************************************************/
  174.  
  175. static void
  176. BaseLineTest() {
  177.     glClear(GL_COLOR_BUFFER_BIT);
  178.     glDisable(GL_LIGHTING);
  179.     glDisable(GL_COLOR_MATERIAL);
  180.     glShadeModel(GL_FLAT);
  181.  
  182.     glNewList(1, GL_COMPILE);
  183.         DrawBaseLines();
  184.     glEndList();
  185.  
  186.     pdbMeasureRate(glFinish, DrawDisplayList, glFinish, Calibrate,
  187.         &BaseLineRate);
  188.     Calibrate = 0;
  189.  
  190.     glDeleteLists(1, 1);
  191.     }
  192.  
  193.  
  194. /*****************************************************************************
  195.  * BaseTriangleTest - measure drawing rate for baseline triangles
  196.  *****************************************************************************/
  197.  
  198. static void
  199. BaseTriangleTest() {
  200.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  201.  
  202.     glEnable(GL_DEPTH_TEST);
  203.     glDepthFunc(GL_LEQUAL);        /* force some drawing to occur */
  204.  
  205.     glNewList(1, GL_COMPILE);
  206.         DrawBaseTriangles();
  207.     glEndList();
  208.  
  209.     pdbMeasureRate(glFinish, DrawDisplayList, glFinish, Calibrate,
  210.         &BaseTriangleRate);
  211.     Calibrate = 0;
  212.  
  213.     glDeleteLists(1, 1);
  214.     }
  215.  
  216.  
  217. /*****************************************************************************
  218.  * DepthBufferingIsFast - see if depth-buffered triangles are at least half as
  219.  *              fast as triangles without depth-buffering
  220.  *****************************************************************************/
  221.  
  222. int
  223. DepthBufferingIsFast(void) {
  224.     if (!RunTest(BaseTriangleTest, cBaseTriangle, &BaseTriangleRate,
  225.         "max rgb, max z"))
  226.         return 0;
  227.  
  228.     if (!RunTest(NoDepthBufferTest, "NoDepthBuffer", &NoDepthBufferRate,
  229.         "max rgb"))
  230.         return 0;
  231.  
  232.     return BaseTriangleRate > 0.5 * NoDepthBufferRate;
  233.     }
  234.  
  235.  
  236. /*****************************************************************************
  237.  * DrawBaseLines - draw a simple line strip
  238.  *
  239.  * The caller must enable the appropriate options, e.g. lighting, depth
  240.  * buffering, texturing.
  241.  *****************************************************************************/
  242.  
  243. static void
  244. DrawBaseLines(void) {
  245.     int i;
  246.  
  247.     glNormal3f(0.0, 0.0, 1.0);
  248.     glBegin(GL_LINE_STRIP);
  249.         for (i = 0; i < sizeof(Vertex) / sizeof(Vertex[0]); i += 2)
  250.             glVertex2fv(Vertex + i);
  251.     glEnd();
  252.     }
  253.  
  254.  
  255. /*****************************************************************************
  256.  * DrawBaseTriangles - draw a simple triangle strip
  257.  *
  258.  * The caller must enable the appropriate options, e.g. lighting, depth
  259.  * buffering, texturing.
  260.  *****************************************************************************/
  261.  
  262. static void
  263. DrawBaseTriangles(void) {
  264.     int i;
  265.  
  266.     glNormal3f(0.0, 0.0, 1.0);
  267.     glBegin(GL_TRIANGLE_STRIP);
  268.         for (i = 0; i < sizeof(Vertex) / sizeof(Vertex[0]); i += 2)
  269.             glVertex2fv(Vertex + i);
  270.     glEnd();
  271.     }
  272.  
  273.  
  274. /*****************************************************************************
  275.  * DrawDisplayList - draw display list created by DisplayListTest
  276.  *****************************************************************************/
  277.  
  278. static void
  279. DrawDisplayList(void) {
  280.     glCallList(1);
  281.     }
  282.  
  283.  
  284. /*****************************************************************************
  285.  * ImmediateModeIsFast - see if immediate-mode triangles are at least half as
  286.  *             fast as display-listed triangles
  287.  *****************************************************************************/
  288.  
  289. int
  290. ImmediateModeIsFast(void) {
  291.     if (!RunTest(BaseTriangleTest, cBaseTriangle, &BaseTriangleRate,
  292.         "max rgb, max z"))
  293.         return 0;
  294.  
  295.     if (!RunTest(ImmediateModeTest, "ImmediateMode", &ImmediateModeRate,
  296.         "max rgb, max z"))
  297.         return 0;
  298.     
  299.     return ImmediateModeRate > 0.5 * BaseTriangleRate;
  300.     }
  301.  
  302.  
  303. /*****************************************************************************
  304.  * ImmediateModeTest - measure drawing rate for immediate-mode triangle strip
  305.  *****************************************************************************/
  306.  
  307. static void
  308. ImmediateModeTest() {
  309.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  310.  
  311.     glEnable(GL_DEPTH_TEST);
  312.     glDepthFunc(GL_LEQUAL);        /* force some drawing to occur */
  313.  
  314.     pdbMeasureRate(glFinish, DrawBaseTriangles, glFinish, Calibrate,
  315.         &ImmediateModeRate);
  316.     Calibrate = 0;
  317.     }
  318.  
  319.  
  320. /*****************************************************************************
  321.  * LineAAIsFast - see if antialiased lines are at least half as fast as
  322.  *          ordinary aliased lines
  323.  *****************************************************************************/
  324.  
  325. int
  326. LineAAIsFast(void) {
  327.     if (!RunTest(BaseLineTest, cBaseLine, &BaseLineRate, "max rgb"))
  328.         return 0;
  329.  
  330.     if (!RunTest(AALineTest, "AALine", &AALineRate, "max rgb"))
  331.         return 0;
  332.  
  333.     return AALineRate > 0.5 * BaseLineRate;
  334.     }
  335.  
  336.  
  337. /*****************************************************************************
  338.  * Measure - create a window, set default OpenGL state, and run a test
  339.  *****************************************************************************/
  340.  
  341. static int
  342. Measure (
  343.     const char*    windowType,
  344.     const char*    windowTitle,
  345.     void    (*testFunc)(void)
  346.     ) {
  347.     static const GLfloat diffuse[] = {0.5, 0.5, 0.5, 1.0};
  348.     static const GLfloat specular[] = {0.5, 0.5, 0.5, 1.0};
  349.     static const GLfloat direction[] = {1.0, 1.0, 1.0, 0.0};
  350.     static const GLfloat matAmbient[] = {0.1, 0.1, 0.1, 1.0};
  351.     static const GLfloat matSpecular[] = {0.5, 0.5, 0.5, 1.0};
  352.  
  353.     if (!IsFastOpenWindow(windowType, windowTitle))
  354.         return 0;
  355.  
  356.     glClearDepth(1.0);
  357.     glClearStencil(0);
  358.  
  359.     glEnable(GL_CULL_FACE);
  360.     glCullFace(GL_BACK);
  361.  
  362.     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
  363.     glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
  364.     glLightfv(GL_LIGHT0, GL_POSITION, direction);
  365.     glEnable(GL_LIGHT0);
  366.     glEnable(GL_LIGHTING);
  367.  
  368.     glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbient);
  369.     glMaterialfv(GL_FRONT, GL_SPECULAR, matSpecular);
  370.     glMateriali(GL_FRONT, GL_SHININESS, 128);
  371.     glEnable(GL_COLOR_MATERIAL);
  372.     glShadeModel(GL_SMOOTH);
  373.  
  374.     glMatrixMode(GL_PROJECTION);
  375.     gluPerspective(45.0, 1.0, 2.4, 4.6);
  376.     glMatrixMode(GL_MODELVIEW);
  377.  
  378.     gluLookAt(0.0,0.0,3.5, 0.0,0.0,0.0, 0.0,1.0,0.0);
  379.  
  380.     (*testFunc)();
  381.  
  382.     IsFastCloseWindow();
  383.     return 1;
  384.     }
  385.  
  386.  
  387. /*****************************************************************************
  388.  * NoDepthBufferTest - draw triangles without depth buffering
  389.  *****************************************************************************/
  390.  
  391. static void
  392. NoDepthBufferTest() {
  393.     glClear(GL_COLOR_BUFFER_BIT);
  394.  
  395.     glDisable(GL_DEPTH_TEST);
  396.  
  397.     glNewList(1, GL_COMPILE);
  398.         DrawBaseTriangles();
  399.     glEndList();
  400.  
  401.     pdbMeasureRate(glFinish, DrawDisplayList, glFinish, Calibrate,
  402.         &NoDepthBufferRate);
  403.     Calibrate = 0;
  404.  
  405.     glDeleteLists(1, 1);
  406.     }
  407.  
  408.  
  409. /*****************************************************************************
  410.  * RunTest - if performance data for a given test is in the database, return
  411.  *         it; otherwise create a window, measure the test's drawing rate,
  412.  *         and save the result in the database
  413.  *****************************************************************************/
  414.  
  415. static int
  416. RunTest (
  417.     void    (*testFunction)(void),
  418.     const char*    testName,
  419.     double*    rate,
  420.     char*    windowType
  421.     ) {
  422.     if (pdbReadRate(ServerName, cIsFast, testName, Version, rate)
  423.         == PDB_NO_ERROR)
  424.         return 1;
  425.  
  426.     if (!Measure(windowType, testName, testFunction))
  427.         /* testFunction sets ``rate'' implicitly */
  428.         return 0;
  429.     
  430.     pdbWriteRate(ServerName, cIsFast, testName, Version, *rate);
  431.  
  432.     return 1;
  433.     }
  434.  
  435.  
  436. /*****************************************************************************
  437.  * StencillingIsFast - see if stencilled triangles are at least half as fast
  438.  *               as non-stencilled triangles
  439.  *****************************************************************************/
  440.  
  441. int
  442. StencillingIsFast(void) {
  443.     if (!RunTest(BaseTriangleTest, cBaseTriangle, &BaseTriangleRate,
  444.         "max rgb, max z"))
  445.         return 0;
  446.  
  447.     if (!RunTest(StencillingTest, "Stencilling", &StencillingRate,
  448.         "max rgb, max z, max s"))
  449.         return 0;
  450.  
  451.     return StencillingRate > 0.5 * BaseTriangleRate;
  452.     }
  453.  
  454.  
  455. /*****************************************************************************
  456.  * StencillingTest - draw triangles with nontrivial stencil operations
  457.  *****************************************************************************/
  458.  
  459. static void
  460. StencillingTest() {
  461.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
  462.         | GL_STENCIL_BUFFER_BIT);
  463.  
  464.     glEnable(GL_DEPTH_TEST);
  465.     glDepthFunc(GL_LEQUAL);
  466.  
  467.     glNewList(1, GL_COMPILE);
  468.         DrawBaseTriangles();
  469.     glEndList();
  470.  
  471.     glEnable(GL_STENCIL_TEST);
  472.     glStencilFunc(GL_EQUAL, 1, 1);
  473.     glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
  474.  
  475.     pdbMeasureRate(glFinish, DrawDisplayList, glFinish, Calibrate,
  476.         &StencillingRate);
  477.     Calibrate = 0;
  478.  
  479.     glDeleteLists(1, 1);
  480.     }
  481.  
  482.  
  483. /*****************************************************************************
  484.  * TextureMappingIsFast - see if texture-mapped triangles are at least half as
  485.  *              fast as ordinary shaded triangles
  486.  *****************************************************************************/
  487.  
  488. int
  489. TextureMappingIsFast(void) {
  490.     if (!RunTest(BaseTriangleTest, cBaseTriangle, &BaseTriangleRate,
  491.         "max rgb, max z"))
  492.         return 0;
  493.  
  494.     if (!RunTest(TextureMappingTest, "TextureMapping", &TextureMappingRate,
  495.         "max rgb, max z"))
  496.         return 0;
  497.  
  498.     return TextureMappingRate > 0.5 * BaseTriangleRate;
  499.     }
  500.  
  501.  
  502. /*****************************************************************************
  503.  * TextureMappingTest - draw baseline triangles with texture mapping
  504.  *****************************************************************************/
  505.  
  506. static void
  507. TextureMappingTest() {
  508.     GLubyte texture[8][8][3];
  509.     int i;
  510.     int j;
  511.     int c;
  512.  
  513.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  514.  
  515.     for (i = 0; i < 8; ++i)
  516.         for (j = 0; j < 8; ++j) {
  517.             c = ((i & 0x1) ^ (j & 0x1))? 255: 0;
  518.             texture[i][j][0] = c;
  519.             texture[i][j][1] = texture[i][j][2] = 0;
  520.             }
  521.  
  522.     glEnable(GL_DEPTH_TEST);
  523.     glDepthFunc(GL_LEQUAL);
  524.  
  525.     glEnable(GL_TEXTURE_2D);
  526.  
  527.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  528.     gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 8, 8, GL_RGB,
  529.         GL_UNSIGNED_BYTE, texture);
  530.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  531.         GL_NEAREST);
  532.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
  533.         GL_NEAREST);
  534.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  535.  
  536.     glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  537.     glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  538.     glEnable(GL_TEXTURE_GEN_S);
  539.     glEnable(GL_TEXTURE_GEN_T);
  540.  
  541.     glMatrixMode(GL_TEXTURE);
  542.     glLoadIdentity();
  543.     glScalef(4.0, 4.0, 1.0);
  544.     glMatrixMode(GL_MODELVIEW);
  545.  
  546.     glNewList(1, GL_COMPILE);
  547.         DrawBaseTriangles();
  548.     glEndList();
  549.  
  550.     pdbMeasureRate(glFinish, DrawDisplayList, glFinish, Calibrate,
  551.         &TextureMappingRate);
  552.     Calibrate = 0;
  553.  
  554.     glDeleteLists(1, 1);
  555.     }
  556.  
  557.  
  558.  
  559. /*****************************************************************************
  560.  * Window-system-specific code for isfast
  561.  *
  562.  * This code isolates window system initialization, window
  563.  * creation/deletion, and OpenGL context creation/deletion.
  564.  *****************************************************************************/
  565.  
  566. #ifdef X11
  567.  
  568. /* X11 Version */
  569. #include <strings.h>
  570. #include <X11/Xlib.h>
  571. #include <X11/Xatom.h>
  572. #include <X11/Xmu/StdCmap.h>
  573. #include "visinfo.h"
  574.  
  575.  
  576. static Display* Dpy = NULL;
  577. static int Scr;
  578. static Window ParentWin;
  579. static Window Win;
  580. static XVisualInfo Vis;
  581. static GLXContext RC;
  582.  
  583.  
  584. static Colormap FindColormap(void);
  585. static Bool WaitForExposure(Display* d, XEvent* e, char* arg);
  586. static int OpenWindow(const char* attributes, const char* title, int mapped);
  587.  
  588.  
  589. int
  590. IsFastXOpenDisplay(const char* displayName) {
  591.     Dpy = XOpenDisplay(displayName);
  592.     if (!Dpy)
  593.         return 0;
  594.  
  595.     if (!glXQueryExtension(Dpy, NULL, NULL)) {
  596.         XCloseDisplay(Dpy);
  597.         Dpy = NULL;
  598.         return 0;
  599.         }
  600.  
  601.     Scr = DefaultScreen(Dpy);
  602.     ParentWin = RootWindow(Dpy, Scr);
  603.  
  604.     if (displayName)
  605.         ServerName = strdup(displayName);
  606.     else
  607.         ServerName = NULL;
  608.     pdbOpen();
  609.     Calibrate = 1;        /* request calibration on first measurement */
  610.     if (OpenWindow("max rgb", "Checking version...", 0)) {
  611.         Version = strdup(glGetString(GL_VERSION));
  612.         IsFastCloseWindow();
  613.         }
  614.     else
  615.         Version = strdup("VERSION?");
  616.  
  617.     return 1;
  618.     }
  619.  
  620. void
  621. IsFastXCloseDisplay(void) {
  622.     if (Dpy) {
  623.         XCloseDisplay(Dpy);
  624.         Dpy = NULL;
  625.         Scr = 0;
  626.         ParentWin = None;
  627.         Win = None;
  628.         if (ServerName) {
  629.             free(ServerName);
  630.             ServerName = NULL;
  631.             }
  632.         if (Version) {
  633.             free(Version);
  634.             Version = NULL;
  635.             }
  636.         pdbClose();
  637.         }
  638.     }
  639.  
  640.  
  641. int
  642. IsFastOpenWindow(const char* attributes, const char* title) {
  643.     return OpenWindow(attributes, title, 1);
  644.     }
  645.  
  646.  
  647. static int
  648. OpenWindow(const char* attributes, const char* title, int mapped) {
  649.     XVisualInfo* vInfo;
  650.     int nVInfo;
  651.     XSetWindowAttributes xswa;
  652.     int x = 0, y = 0, w = 256, h = 256;
  653.     XEvent event;
  654.  
  655.     if (!visPixelFormat(attributes))
  656.         return 0;    /* syntax error in Visual criteria */
  657.  
  658.     vInfo = visGetGLXVisualInfo(Dpy, Scr, &nVInfo);
  659.     if (nVInfo == 0)
  660.         return 0;    /* no matching Visuals */
  661.     Vis = *vInfo;
  662.     free(vInfo);
  663.  
  664.     RC = glXCreateContext(Dpy, &Vis, 0, GL_TRUE);
  665.     if (!RC)
  666.         return 0;
  667.  
  668.     xswa.border_pixel = 0;
  669.     xswa.colormap = FindColormap();
  670.     xswa.event_mask = ExposureMask;
  671.     Win = XCreateWindow(Dpy, ParentWin, x, y, w, h, 0, Vis.depth,
  672.         InputOutput, Vis.visual,
  673.         CWColormap|CWEventMask|CWBorderPixel, &xswa);
  674.     if (Win == None)
  675.         return 0;
  676.  
  677.     if (ParentWin == RootWindow(Dpy, Scr)) {
  678.         Atom wmDeleteWindow;
  679.         XSizeHints sh;
  680.  
  681.         wmDeleteWindow = XInternAtom(Dpy, "WM_DELETE_WINDOW", False);
  682.         XSetWMProtocols(Dpy, Win, &wmDeleteWindow, 1);
  683.  
  684.         sh.x = x;
  685.         sh.y = y;
  686.         sh.width = w;
  687.         sh.height = h;
  688.         sh.flags = USPosition | USSize;
  689.         XSetStandardProperties(Dpy, Win, title, title, None, NULL, 0,
  690.             &sh);
  691.         }
  692.  
  693.     if (mapped) {
  694.         XMapWindow(Dpy, Win);
  695.         XIfEvent(Dpy, &event, WaitForExposure, (char*) Win);
  696.         }
  697.  
  698.     glXMakeCurrent(Dpy, Win, RC);
  699.     glViewport(x, y, w, h);
  700.  
  701.     return 1;
  702.     }
  703.  
  704.  
  705. void
  706. IsFastCloseWindow(void) {
  707.     glXMakeCurrent(Dpy, None, NULL);
  708.     glXDestroyContext(Dpy, RC);
  709.     XDestroyWindow(Dpy, Win);
  710.     }
  711.  
  712.  
  713. static Colormap
  714. FindColormap(void) {
  715.         Status status;
  716.         XStandardColormap* standardCmaps;
  717.         int i;
  718.         int nCmaps;
  719.     Colormap cmap;
  720.                 
  721.         if (Vis.class != TrueColor)
  722.                 return None;
  723.         status = XmuLookupStandardColormap(Dpy, Scr, Vis.visualid,
  724.                 Vis.depth, XA_RGB_DEFAULT_MAP, False, True);
  725.         if (status == 1) {
  726.                 status = XGetRGBColormaps(Dpy, RootWindow(Dpy, Scr),
  727.                         &standardCmaps, &nCmaps, XA_RGB_DEFAULT_MAP);
  728.                 if (status == 1) {
  729.                         for (i = 0; i < nCmaps; ++i)
  730.                                 if (standardCmaps[i].visualid == Vis.visualid) {
  731.                     cmap = standardCmaps[i].colormap;
  732.                                         XFree(standardCmaps);
  733.                                         return cmap;
  734.                                         }
  735.                         }
  736.                 }
  737.  
  738.         cmap = XCreateColormap(Dpy, ParentWin, Vis.visual, AllocNone);
  739.     return cmap;
  740.     }
  741.  
  742.  
  743. static Bool
  744. WaitForExposure(Display* d, XEvent* e, char* arg) {
  745.     return (e->type == Expose)
  746.         && (e->xexpose.window == (Window) arg)
  747.         && (e->xexpose.count == 0);
  748.     }
  749.  
  750. #endif    /* X11 */
  751.  
  752.  
  753.  
  754. /* This space reserved for window-system-specific code of your choice... */
  755.